package jay.home.bet.domain.logic;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

import jay.home.bet.domain.Item;
import jay.home.bet.domain.Order;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Calculator
{
	protected final static Log logger = LogFactory.getLog(Calculator.class);
	
	/**
	 * usage guide : http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/index.html
	 * the specification : JSR 223.
	 * the reference implementation can be downloaded from jcp.org website. contains javax.script.* package and rhino
	 */
	static ScriptEngine engine;
	static
	{
		ScriptEngineManager factory = new ScriptEngineManager();
		engine = factory.getEngineByName("JavaScript");
		InputStream stream = Calculator.class.getClassLoader().getResourceAsStream("算法.js");
		try
		{
			InputStreamReader reader = new InputStreamReader(stream, "utf-8");
			engine.eval(reader);
		}catch(Exception e)
		{
			logger.fatal("加载业务算法出现问题, 系统不能正常运行!!!==>\n" + e);
			e.printStackTrace();
		}
	}
	
	/**
	 *  context是有格式的计算赔率所需要的信息, 比如:<br/>
	 *  {  
	 *    cat:'让球', 
	 *    context : {odd:0.8, beton:'主', pankou:'0.5/1', who2who:'主让客', result:'3:2'},
	 *    amount : 1000
	 *  }
	 *  <br/>
	 *  具体信息参照"算法.js"文件
	 */
	public static Double cal(String context)
	{
		Double result = null;
		try
		{
			Invocable inv = (Invocable)engine;
			result = (Double)inv.invokeFunction("calc", context);
		} catch (Exception e)
		{
			logger.warn("调用业务算法时出现异常..." + e);
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 根据一个完备的order对象, 调用赔率算法引擎, 计算出输/赢了多少钱.即派彩.结果没有扣除本金.<br/> 
	 * @return
	 */
	public static Double cal(Order order)
	{
		StringBuffer bet = new StringBuffer();
		List<Item> items = order.getItems();
		String amount = order.getAmount().toString();
		String cat = order.getCat();
//		初步结果: {cat:'大小', amount:1000, 
		bet.append("{cat:'").append(cat).append("',").append("amount:").append(amount).append(",");
		if("过关".equals(cat))
		{
			bet.append("context:[");
			for(Item item : items)
			{
				Double odd = item.getOdd();
				if("让球".equals(item.getCat()) || "大小".equals(item.getCat()))
					odd += 1;//让球和大小默认是不把成本计入的, 所以要加1然后再算
				bet.append("{odd:").append(odd.toString());
				bet.append(", cat:'").append(item.getCat());
				bet.append("', beton:'").append(item.getBeton());
				bet.append("', pankou:'").append(item.getPankou());
				bet.append("', who2who:'").append(item.getAttach());
				if(item.getCurrentScore() != null)//根据它判断是不是滚球
					bet.append("', result:'").append(item.getCurrentScore()).append("/").append(item.getResultScore());
				else bet.append("', result:'").append(item.getResultScore());
				bet.append("'},");
			}
			bet.append("]}");
		}
		else
		{
			bet.append("context:");
			Item item = items.get(0);
			Double odd = item.getOdd();
			if ("让球".equals(item.getCat()) || "大小".equals(item.getCat()))
				odd += 1;// 让球和大小默认是不把成本计入的, 所以要加1然后再算
			bet.append("{odd:").append(odd.toString());
			bet.append(", beton:'").append(item.getBeton());
			bet.append("', pankou:'").append(item.getPankou());
			bet.append("', who2who:'").append(item.getAttach());
			if (item.getCurrentScore() == null)// 根据它判断是不是滚球
				bet.append("', result:'").append(item.getCurrentScore()).append("/").append(item.getResultScore());
			else
				bet.append("', result:'").append(item.getResultScore());
			bet.append("'}}");
		}
		return cal(bet.toString());
	}
}
